
#include <message.h>

#define NUM_MESSAGES 64

//Message Handling

//Message free list - used as stack
//typedef struct basic_list basic_list;
//struct basic_list
//{
//  void* msg;
//  basic_list* prev;
//  basic_list* next;
//} ;

//static basic_list msg_free_list[NUM_MESSAGES];
static Message** msg_free_list;//[NUM_MESSAGES];
static uint8_t last_free_msg_id;
static Message* messages;//[NUM_MESSAGES];

static void push_free_message(Message* msg)
{
  if(unlikely(last_free_msg_id >= NUM_MESSAGES)) {
    fprintf(stderr, "PANIC!!! No more free message space available\n");
    exit(-1);
  }

  last_free_msg_id++;
  msg_free_list[last_free_msg_id] = msg;
}

static Message* pop_free_message()
{
  if(unlikely(last_free_msg_id == 0)) {
    fprintf(stderr,"PANIC!! No more free messages available\n");
    exit(-1);
  }

  int i = last_free_msg_id;
  last_free_msg_id--;
  return msg_free_list[i];
}

static void init_free_message()
{
  //put all the messages into free message list
  int i=0;
  for(i=0;i<NUM_MESSAGES; i++)
    msg_free_list[i] = &messages[i];

  last_free_msg_id = NUM_MESSAGES - 1;
}

void init_messages()
{
  //initialize messages
//  memset(messages,0,sizeof(Message)*NUM_MESSAGES);
  messages = calloc(NUM_MESSAGES, sizeof(Message));
  msg_free_list = calloc(NUM_MESSAGES, sizeof(Message*));
  init_free_message();
}

static Message* get_free_message()
{
  Message* msg = pop_free_message();
  msg->from = NULL;
  msg->opaque = NULL;
  msg->addr = -1;
  msg->type = -1;
  msg->data = -1;
  msg->size = -1;
  return msg;
}

//Message Functions
Message* sim_new_write_msg(void* op, uint64_t _addr, uint64_t _data, int _size)
{
//  Message* _wmsg = calloc(1,sizeof(Message));
  Message* _wmsg = get_free_message();
  _wmsg->type = WRITE_MSG;
  _wmsg->opaque = op;
  _wmsg->addr = _addr;
  _wmsg->data = _data;
  _wmsg->size = _size;
  _wmsg->from = NULL;
//  _wmsg->to = NULL;
  return _wmsg;
}

Message* sim_new_read_msg(void* op, uint64_t _addr, int _size)
{
//  Message* _rmsg = calloc(1,sizeof(Message));
  Message* _rmsg = get_free_message();
  _rmsg->type = READ_MSG;
  _rmsg->opaque = op;
  _rmsg->addr = _addr;
  _rmsg->data = -1;
  _rmsg->size = _size;
  _rmsg->from = NULL;
//  _rmsg->to = NULL;
  return _rmsg;
}

void sim_delete_message(Message* msg)
{
  push_free_message(msg);
}

